;******************** (C) COPYRIGHT 2011 STMicroelectronics ********************
;* File Name          : startup_stm32f10x_md.s
;* Author             : MCD Application Team
;* Version            : V3.5.0
;* Date               : 11-March-2011
;* Description        : STM32F10x Medium Density Devices vector table for MDK-ARM 
;*                      toolchain.  
;*                      This module performs:
                        ; 设置栈的大小
;*                      - Set the initial SP
                        ; 设置PC的初始值
;*                      - Set the initial PC == Reset_Handler
                        ; 设置向量表
;*                      - Set the vector table entries with the exceptions ISR address
                        ; 设置时钟
;*                      - Configure the clock system
;*                      - Branches to __main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the CortexM3 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.
;* <<< Use Configuration Wizard in Context Menu >>>   
;*******************************************************************************
; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
;*******************************************************************************

; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

;=================
; ARM的指令格式如下
; 标号   操作码  操作数  注释
; [label] operation [operands] ; comments
;=================


;==============
; EQUs是定义符号的指令
; 相当于C语言中的#define
; 将Stack_Size定义为0x00000400
; 栈设置400H，也就是1024字节
;==============
Stack_Size      EQU     0x00000400

                ;AREA 段名, 属性, 类型, 对齐
                ;==================
                ; 接下来的 AREA STACK, NOINIT, READWRITE, ALIGN=3 是一个 AREA 指令，
                ; 它定义了一个名为 STACK 的内存区域。
                ; NOINIT 表示这个区域在开始时不会被初始化，
                ; READWRITE 表示这个区域可以进行读写操作，
                ; ALIGN=3 表示这个区域的地址将被对齐到2的3次方，也就是8字节边界
                ;==================
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
;==================
; Stack_Mem SPACE Stack_Size 这行代码在 STACK 区域中分配了 Stack_Size 大小的空间，也就是1024字节。
;==================
Stack_Mem       SPACE   Stack_Size
; 申请内存的结束地址，也就是栈顶指针
__initial_sp


; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

; 将Heap_Size定义为0x00000200
; 堆设置200H，也就是512字节
;==================
; Heap_Size EQU 0x00000200 这行代码定义了一个名为 Heap_Size 的符号，其值等于 0x00000200。
; 这表示我们将堆大小设置为512字节（0x200是512的十六进制表示）
;==================
Heap_Size       EQU     0x00000200

                ;=========================
                ;AREA 段名, 属性, 类型, 对齐
                ;=========================
                ; AREA HEAP, NOINIT, READWRITE, ALIGN=3 是一个 AREA 指令，它定义了一个名为 HEAP 的内存区域。
                ; NOINIT 表示这个区域在开始时不会被初始化，
                ; READWRITE 表示这个区域可以进行读写操作，
                ; ALIGN=3 表示这个区域的地址将被对齐到2的3次方，也就是8字节边界。
                ;=========================
                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
;=========================
; __heap_base 和 __heap_limit 是两个特殊的符号。
; __heap_base 通常被定义为堆区域的底部，而 __heap_limit 则被定义为堆区域的顶部。
; 在程序运行过程中，如果堆的使用超过了 __heap_limit，那么程序就会出现堆溢出错误。
;=========================
__heap_base
;=========================
; Heap_Mem SPACE Heap_Size 这行代码在 HEAP 区域中分配了 Heap_Size 大小的空间，也就是512字节。
;=========================
Heap_Mem        SPACE   Heap_Size
;=========================
; __heap_base 和 __heap_limit 是两个特殊的符号。
; __heap_base 通常被定义为堆区域的底部，而 __heap_limit 则被定义为堆区域的顶部。
; 在程序运行过程中，如果堆的使用超过了 __heap_limit，那么程序就会出现堆溢出错误。
;=========================
__heap_limit

                ;=============================
                ; 这段代码是用汇编语言编写的，主要用于定义STM32F10x微控制器的向量表。向量表是一种特殊的数据结构，用于存储中断处理程序的地址。当中断发生时，微控制器会根据向量表跳转到相应的中断处理程序。

                ;首先，PRESERVE8 和 THUMB 是两个指令。PRESERVE8 用于确保堆栈对齐到8字节边界，这是ARM架构的要求。THUMB 则表示接下来的代码应以Thumb指令集（一种精简的ARM指令集）编译。

                ;接下来的 AREA RESET, DATA, READONLY 定义了一个名为 RESET 的内存区域。RESET 区域是一个只读的数据区域，用于存储向量表。在 RESET 区域中，我们定义了一个名为 __Vectors 的标号，它是向量表的起始地址。__Vectors_End 和 __Vectors_Size 是两个特殊的符号，分别表示向量表的结束地址和大小。

                PRESERVE8
                THUMB



; Vector Table Mapped to Address 0 at Reset

                ;===========================
                ; 接下来的 AREA RESET, DATA, READONLY 是一个 AREA 指令，
                ; 它定义了一个名为 RESET 的内存区域。DATA 表示这个区域用于存储数据，READONLY 表示这个区域只读，不能写入。
                ;===========================
                AREA    RESET, DATA, READONLY
                ;===========================
                ; EXPORT __Vectors、EXPORT __Vectors_End 和 EXPORT __Vectors_Size 是三个 EXPORT 指令，
                ; 它们将 __Vectors、__Vectors_End 和 __Vectors_Size 这三个符号导出，使得这些符号可以在其他文件中被访问。
                ; 这三个符号通常用于表示向量表的开始位置、结束位置和大小。
                ; __Vectors = __Vectore_End - __Vectors
                ;===========================
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size

;================
; __Vectors是一个标号，它表示向量表的起始地址，默认是0x00000000。
; DCD：Data Constant Double Word
; 分配一段连续字（32位）4字节的内存
; CPU在复位时，会把这个地址0x00000000加载到SP寄存器中
; __initial_sp是栈的起始地址
; CPU在复位时，会把这个地址0x00000004加载到PC寄存器中
; 所以程序上电的第一个程序是Reset_Handler
; Reset_Handler是复位中断的处理函数
;================


__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
                DCD     MemManage_Handler          ; MPU Fault Handler
                DCD     BusFault_Handler           ; Bus Fault Handler
                DCD     UsageFault_Handler         ; Usage Fault Handler
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     SVC_Handler                ; SVCall Handler
                DCD     DebugMon_Handler           ; Debug Monitor Handler
                DCD     0                          ; Reserved
                DCD     PendSV_Handler             ; PendSV Handler
                DCD     SysTick_Handler            ; SysTick Handler

                ; External Interrupts
                DCD     WWDG_IRQHandler            ; Window Watchdog
                DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
                DCD     TAMPER_IRQHandler          ; Tamper
                DCD     RTC_IRQHandler             ; RTC
                DCD     FLASH_IRQHandler           ; Flash
                DCD     RCC_IRQHandler             ; RCC
                DCD     EXTI0_IRQHandler           ; EXTI Line 0
                DCD     EXTI1_IRQHandler           ; EXTI Line 1
                DCD     EXTI2_IRQHandler           ; EXTI Line 2
                DCD     EXTI3_IRQHandler           ; EXTI Line 3
                DCD     EXTI4_IRQHandler           ; EXTI Line 4
                DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
                DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
                DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
                DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
                DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
                DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
                DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
                DCD     ADC1_2_IRQHandler          ; ADC1_2
                DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
                DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
                DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
                DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
                DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
                DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
                DCD     TIM1_UP_IRQHandler         ; TIM1 Update
                DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
                DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare
                DCD     TIM2_IRQHandler            ; TIM2
                DCD     TIM3_IRQHandler            ; TIM3
                DCD     TIM4_IRQHandler            ; TIM4
                DCD     I2C1_EV_IRQHandler         ; I2C1 Event
                DCD     I2C1_ER_IRQHandler         ; I2C1 Error
                DCD     I2C2_EV_IRQHandler         ; I2C2 Event
                DCD     I2C2_ER_IRQHandler         ; I2C2 Error
                DCD     SPI1_IRQHandler            ; SPI1
                DCD     SPI2_IRQHandler            ; SPI2
                DCD     USART1_IRQHandler          ; USART1
                DCD     USART2_IRQHandler          ; USART2
                DCD     USART3_IRQHandler          ; USART3
                DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
                DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line
                DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors

                ;===================
                ; 在这行代码中，|.text| 是区域的名称，CODE 是区域的类型，READONLY 是区域的属性。
                ; |.text| 是一个常见的区域名称，通常用于存储程序的代码部分。
                ; 在这里，它被包围在两个竖线中，这是因为 .text 在 ARM 汇编语言中是一个保留字，包围在竖线中可以避免语法错误。
                ; CODE 表示这个区域用于存储代码。这意味着这个区域中的内容会被 CPU 执行。
                ; READONLY 表示这个区域是只读的，不能被写入。这是因为代码区域通常是只读的，以防止程序在运行时修改自己的代码。 
                ; 总的来说，这行代码的目的是在内存中定义一个用于存储代码的只读区域，这个区域的名称是 .text。
                ;====================
                AREA    |.text|, CODE, READONLY

; Reset handler
;================
; PROC   与  ENDP 之间就是Reset_Handler的函数体
;================
; 这段代码是用汇编语言编写的，它定义了一个名为 Reset_Handler 的过程，
; 这个过程是微控制器（如STM32F10x）在复位（即开机或重启）时执行的第一个程序。
;================
Reset_Handler    PROC
                 ;==========================
                 ; EXPORT Reset_Handler [WEAK] 是一个 EXPORT 指令，它将 Reset_Handler 标号导出，使得这个标号可以在其他文件中被访问。
                 ; WEAK 表示这个标号是一个弱符号，这意味着如果在其他文件中定义了同名的标号，那么这个标号就会被覆盖。
                 ;==========================
                 EXPORT  Reset_Handler             [WEAK]
     
     ;========================
     ; IMPORT __main 和 IMPORT SystemInit 是两个 IMPORT 指令，它们导入了 __main 和 SystemInit 这两个符号。
     ; 这两个符号通常在其他文件中定义，
     ; __main 通常是C程序的入口点，会做一些初始化，然后调用用户写的main函数；
     ; SystemInit 通常是系统初始化函数。
     ;========================
    
     IMPORT  __main
     IMPORT  SystemInit
                ;==============
                ; LDR R0, =SystemInit
                ; 将SystemInit的地址加载到R0寄存器中
                ;==============

                ;===========
                ; 跳转到对应地址执行
                ; BX R0
                ;===========                 
                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP
;=======================
; 总的来说，这段代码的目的是定义复位处理程序，这个程序在微控制器复位时首先调用 SystemInit 函数进行系统初始化，然后跳转到 __main 函数开始执行用户的程序。
;=======================

; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                ;===========
                ; .表示当前行地址
                ; B表示跳转
                ; B . 表示无限循环
                ; B       .
                ;===========
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
MemManage_Handler\
                PROC
                EXPORT  MemManage_Handler          [WEAK]
                B       .
                ENDP
BusFault_Handler\
                PROC
                EXPORT  BusFault_Handler           [WEAK]
                B       .
                ENDP
UsageFault_Handler\
                PROC
                EXPORT  UsageFault_Handler         [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler                [WEAK]
                B       .
                ENDP
DebugMon_Handler\
                PROC
                EXPORT  DebugMon_Handler           [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler             [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP

Default_Handler PROC

                EXPORT  WWDG_IRQHandler            [WEAK]
                EXPORT  PVD_IRQHandler             [WEAK]
                EXPORT  TAMPER_IRQHandler          [WEAK]
                EXPORT  RTC_IRQHandler             [WEAK]
                EXPORT  FLASH_IRQHandler           [WEAK]
                EXPORT  RCC_IRQHandler             [WEAK]
                EXPORT  EXTI0_IRQHandler           [WEAK]
                EXPORT  EXTI1_IRQHandler           [WEAK]
                EXPORT  EXTI2_IRQHandler           [WEAK]
                EXPORT  EXTI3_IRQHandler           [WEAK]
                EXPORT  EXTI4_IRQHandler           [WEAK]
                EXPORT  DMA1_Channel1_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel2_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel3_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel4_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel5_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel6_IRQHandler   [WEAK]
                EXPORT  DMA1_Channel7_IRQHandler   [WEAK]
                EXPORT  ADC1_2_IRQHandler          [WEAK]
                EXPORT  USB_HP_CAN1_TX_IRQHandler  [WEAK]
                EXPORT  USB_LP_CAN1_RX0_IRQHandler [WEAK]
                EXPORT  CAN1_RX1_IRQHandler        [WEAK]
                EXPORT  CAN1_SCE_IRQHandler        [WEAK]
                EXPORT  EXTI9_5_IRQHandler         [WEAK]
                EXPORT  TIM1_BRK_IRQHandler        [WEAK]
                EXPORT  TIM1_UP_IRQHandler         [WEAK]
                EXPORT  TIM1_TRG_COM_IRQHandler    [WEAK]
                EXPORT  TIM1_CC_IRQHandler         [WEAK]
                EXPORT  TIM2_IRQHandler            [WEAK]
                EXPORT  TIM3_IRQHandler            [WEAK]
                EXPORT  TIM4_IRQHandler            [WEAK]
                EXPORT  I2C1_EV_IRQHandler         [WEAK]
                EXPORT  I2C1_ER_IRQHandler         [WEAK]
                EXPORT  I2C2_EV_IRQHandler         [WEAK]
                EXPORT  I2C2_ER_IRQHandler         [WEAK]
                EXPORT  SPI1_IRQHandler            [WEAK]
                EXPORT  SPI2_IRQHandler            [WEAK]
                EXPORT  USART1_IRQHandler          [WEAK]
                EXPORT  USART2_IRQHandler          [WEAK]
                EXPORT  USART3_IRQHandler          [WEAK]
                EXPORT  EXTI15_10_IRQHandler       [WEAK]
                EXPORT  RTCAlarm_IRQHandler        [WEAK]
                EXPORT  USBWakeUp_IRQHandler       [WEAK]

WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
RTC_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Channel1_IRQHandler
DMA1_Channel2_IRQHandler
DMA1_Channel3_IRQHandler
DMA1_Channel4_IRQHandler
DMA1_Channel5_IRQHandler
DMA1_Channel6_IRQHandler
DMA1_Channel7_IRQHandler
ADC1_2_IRQHandler
USB_HP_CAN1_TX_IRQHandler
USB_LP_CAN1_RX0_IRQHandler
CAN1_RX1_IRQHandler
CAN1_SCE_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_IRQHandler
TIM1_UP_IRQHandler
TIM1_TRG_COM_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTCAlarm_IRQHandler
USBWakeUp_IRQHandler

                B       .

                ENDP

                ALIGN

;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
;=======================
; 这段代码的目的是根据是否定义了 __MICROLIB 符号，来选择不同的方式设置堆和栈。
; 如果定义了 __MICROLIB 符号，那么直接导出堆和栈的相关信息；
; 如果没有定义 __MICROLIB 符号，那么通过 __user_initial_stackheap 过程设置堆和栈。
;=======================
                 IF      :DEF:__MICROLIB           
                
                 EXPORT  __initial_sp
                 EXPORT  __heap_base
                 EXPORT  __heap_limit
                
                 ELSE
                
                 IMPORT  __use_two_region_memory
                 EXPORT  __user_initial_stackheap
                 
__user_initial_stackheap

                 LDR     R0, =  Heap_Mem
                 LDR     R1, =(Stack_Mem + Stack_Size)
                 LDR     R2, = (Heap_Mem +  Heap_Size)
                 LDR     R3, = Stack_Mem
                 BX      LR

                 ALIGN

                 ENDIF

                 END

;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****
